package com.zenithmind.user.service.domain.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.zenithmind.common.result.Result;
import com.zenithmind.common.security.SecurityUtils;
import com.zenithmind.user.mapper.UserMapper;
import com.zenithmind.user.mapper.UserRoleMapper;
import com.zenithmind.user.pojo.domain.User;
import com.zenithmind.user.pojo.domain.UserRole;
import com.zenithmind.user.pojo.dto.RegisterDTO;
import com.zenithmind.user.pojo.dto.UserProfileUpdateDTO;
import com.zenithmind.user.pojo.vo.UserVO;
import com.zenithmind.user.service.domain.UserManagementService;
import com.zenithmind.user.service.domain.UserQueryService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 用户管理服务实现类
 * 遵循单一职责原则：专门负责用户管理相关功能
 * 遵循开闭原则：通过接口扩展管理功能
 * 遵循依赖倒置原则：依赖UserMapper和UserQueryService抽象
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserManagementServiceImpl implements UserManagementService {

    private final UserMapper userMapper;
    private final UserRoleMapper userRoleMapper;
    private final UserQueryService userQueryService;
    private final PasswordEncoder passwordEncoder;

    @Override
    @Transactional
    public Result<UserVO> register(RegisterDTO registerDTO) {
        // 检查用户名是否已存在
        if (userQueryService.existsByUsername(registerDTO.getUsername())) {
            return Result.fail("用户名已存在");
        }

        // 检查邮箱是否已存在
        if (StringUtils.hasText(registerDTO.getEmail()) &&
            userQueryService.existsByEmail(registerDTO.getEmail())) {
            return Result.fail("邮箱已被使用");
        }

        // 创建用户
        User user = new User();
        user.setUsername(registerDTO.getUsername());
        user.setPassword(passwordEncoder.encode(registerDTO.getPassword()));
        // RegisterDTO中没有nickname和mobile字段，使用默认值或从username生成
        user.setNickname(registerDTO.getUsername()); // 使用用户名作为默认昵称
        user.setEmail(registerDTO.getEmail());
        user.setStatus(1); // 默认启用
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        
        // 保存用户
        int result = userMapper.insert(user);
        if (result > 0) {
            UserVO userVO = convertToUserVO(user);
            log.info("用户注册成功：{}", user.getUsername());
            return Result.success(userVO);
        } else {
            return Result.fail("注册失败");
        }
    }

    @Override
    @Transactional
    @CacheEvict(value = {"user:id", "user:username", "user:email"}, allEntries = true)
    public UserVO addOrUpdateUser(User user) {
        if (StringUtils.hasText(user.getId())) {
            // 更新用户
            user.setUpdateTime(LocalDateTime.now());
            user.setUpdateBy(SecurityUtils.getCurrentUserId());
            userMapper.updateById(user);
            log.info("更新用户成功：{}", user.getUsername());
        } else {
            // 新增用户
            user.setCreateTime(LocalDateTime.now());
            user.setUpdateTime(LocalDateTime.now());
            user.setCreateBy(SecurityUtils.getCurrentUserId());
            user.setUpdateBy(SecurityUtils.getCurrentUserId());
            userMapper.insert(user);
            log.info("新增用户成功：{}", user.getUsername());
        }
        
        return convertToUserVO(user);
    }

    @Override
    @Transactional
    public UserVO updateProfile(UserProfileUpdateDTO updateDTO) {
        // 获取当前登录用户ID
        String currentUserId = SecurityUtils.getCurrentUserId();
        if (!StringUtils.hasText(currentUserId)) {
            throw new RuntimeException("用户未登录");
        }

        User user = userQueryService.getUserById(currentUserId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        
        // 更新用户信息
        if (StringUtils.hasText(updateDTO.getNickname())) {
            user.setNickname(updateDTO.getNickname());
        }
        if (StringUtils.hasText(updateDTO.getEmail())) {
            // 检查邮箱是否被其他用户使用
            User existingUser = userQueryService.getUserByEmail(updateDTO.getEmail());
            if (existingUser != null && !existingUser.getId().equals(user.getId())) {
                throw new RuntimeException("邮箱已被其他用户使用");
            }
            user.setEmail(updateDTO.getEmail());
        }
        if (StringUtils.hasText(updateDTO.getMobile())) {
            user.setMobile(updateDTO.getMobile());
        }
        if (StringUtils.hasText(updateDTO.getAvatar())) {
            user.setAvatar(updateDTO.getAvatar());
        }
        if (StringUtils.hasText(updateDTO.getIntro())) {
            user.setIntro(updateDTO.getIntro());
        }
        
        user.setUpdateTime(LocalDateTime.now());
        user.setUpdateBy(SecurityUtils.getCurrentUserId());
        
        userMapper.updateById(user);
        log.info("更新用户档案成功：{}", user.getUsername());
        
        return convertToUserVO(user);
    }

    @Override
    @Transactional
    @CacheEvict(value = {"user:id", "user:username", "user:email"}, key = "#user.id")
    public UserVO updateStatus(User user) {
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getId, user.getId())
                    .set(User::getStatus, user.getStatus())
                    .set(User::getUpdateTime, LocalDateTime.now())
                    .set(User::getUpdateBy, SecurityUtils.getCurrentUserId());
        
        userMapper.update(null, updateWrapper);
        log.info("更新用户状态成功：用户ID={}, 状态={}", user.getId(), user.getStatus());
        
        User updatedUser = userQueryService.getUserById(user.getId());
        return convertToUserVO(updatedUser);
    }

    @Override
    @Transactional
    public UserVO updateRole(UserRole userRole) {
        // 这里应该调用角色相关的服务
        // 暂时简化处理
        log.info("更新用户角色：用户ID={}, 角色ID={}", userRole.getUserId(), userRole.getRoleId());
        
        User user = userQueryService.getUserById(userRole.getUserId());
        return convertToUserVO(user);
    }

    @Override
    @Transactional
    @CacheEvict(value = {"user:id", "user:username", "user:email"}, key = "#user.id")
    public void resetPassword(User user) {
        String defaultPassword = "123456"; // 默认密码
        String encodedPassword = passwordEncoder.encode(defaultPassword);
        
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getId, user.getId())
                    .set(User::getPassword, encodedPassword)
                    .set(User::getUpdateTime, LocalDateTime.now())
                    .set(User::getUpdateBy, SecurityUtils.getCurrentUserId());
        
        userMapper.update(null, updateWrapper);
        log.info("重置用户密码成功：{}", user.getUsername());
    }

    @Override
    @Transactional
    @CacheEvict(value = {"user:id", "user:username", "user:email"}, key = "#userId")
    public void deleteUser(String userId) {
        // 软删除
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getId, userId)
                    .set(User::getIsDeleted, 1)
                    .set(User::getUpdateTime, LocalDateTime.now())
                    .set(User::getUpdateBy, SecurityUtils.getCurrentUserId());
        
        userMapper.update(null, updateWrapper);
        log.info("删除用户成功：用户ID={}", userId);
    }

    @Override
    @Transactional
    @CacheEvict(value = {"user:id", "user:username", "user:email"}, allEntries = true)
    public void deleteBatch(List<String> ids) {
        if (ids == null || ids.isEmpty()) {
            return;
        }
        
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.in(User::getId, ids)
                    .set(User::getIsDeleted, 1)
                    .set(User::getUpdateTime, LocalDateTime.now())
                    .set(User::getUpdateBy, SecurityUtils.getCurrentUserId());
        
        userMapper.update(null, updateWrapper);
        log.info("批量删除用户成功：数量={}", ids.size());
    }

    @Override
    @Transactional
    @CacheEvict(value = {"user:id", "user:username", "user:email"}, key = "#userId")
    public void enableUser(String userId) {
        updateUserStatus(userId, 1);
        log.info("启用用户成功：用户ID={}", userId);
    }

    @Override
    @Transactional
    @CacheEvict(value = {"user:id", "user:username", "user:email"}, key = "#userId")
    public void disableUser(String userId) {
        updateUserStatus(userId, 0);
        log.info("禁用用户成功：用户ID={}", userId);
    }

    @Override
    @Transactional
    public boolean updateStorageUsed(String userId, long fileSize) {
        User user = userQueryService.getUserById(userId);
        if (user == null) {
            return false;
        }
        
        long newStorageUsed = user.getStorageUsed() + fileSize;
        if (newStorageUsed > user.getStorageLimit()) {
            log.warn("用户存储空间不足：用户ID={}, 当前使用={}, 限制={}, 新增={}", 
                    userId, user.getStorageUsed(), user.getStorageLimit(), fileSize);
            return false;
        }
        
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getId, userId)
                    .set(User::getStorageUsed, newStorageUsed)
                    .set(User::getUpdateTime, LocalDateTime.now());
        
        userMapper.update(null, updateWrapper);
        log.info("更新用户存储使用量成功：用户ID={}, 新使用量={}", userId, newStorageUsed);
        return true;
    }

    @Override
    @Transactional
    public void assignRole(String userId, String roleId) {
        // 检查是否已存在该角色分配
        LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserRole::getUserId, userId)
                   .eq(UserRole::getRoleId, roleId)
                   .eq(UserRole::getIsDeleted, 0);
        
        UserRole existingUserRole = userRoleMapper.selectOne(queryWrapper);
        if (existingUserRole != null) {
            log.warn("用户角色已存在：用户ID={}, 角色ID={}", userId, roleId);
            return;
        }
        
        // 创建新的用户角色关联
        UserRole userRole = new UserRole();
        userRole.setUserId(userId);
        userRole.setRoleId(roleId);
        userRole.setCreateTime(LocalDateTime.now());
        userRole.setUpdateTime(LocalDateTime.now());
        userRole.setCreateBy(SecurityUtils.getCurrentUserId());
        userRole.setUpdateBy(SecurityUtils.getCurrentUserId());
        
        userRoleMapper.insert(userRole);
        log.info("分配角色成功：用户ID={}, 角色ID={}", userId, roleId);
    }

    @Override
    @Transactional
    public void removeRole(String userId, String roleId) {
        LambdaUpdateWrapper<UserRole> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(UserRole::getUserId, userId)
                    .eq(UserRole::getRoleId, roleId)
                    .set(UserRole::getIsDeleted, 1)
                    .set(UserRole::getUpdateTime, LocalDateTime.now())
                    .set(UserRole::getUpdateBy, SecurityUtils.getCurrentUserId());
        
        userRoleMapper.update(null, updateWrapper);
        log.info("移除用户角色成功：用户ID={}, 角色ID={}", userId, roleId);
    }

    /**
     * 更新用户状态的私有方法
     * 遵循DRY原则：避免重复代码
     */
    private void updateUserStatus(String userId, Integer status) {
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getId, userId)
                    .set(User::getStatus, status)
                    .set(User::getUpdateTime, LocalDateTime.now())
                    .set(User::getUpdateBy, SecurityUtils.getCurrentUserId());
        
        userMapper.update(null, updateWrapper);
    }

    /**
     * 转换为UserVO
     * 遵循单一职责原则：专门负责实体到VO的转换
     */
    private UserVO convertToUserVO(User user) {
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }
}
